home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / prserr.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  39KB  |  1,388 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /********************************************************************
  10.  *                                    
  11.  *              *****************               
  12.  *              *  P R S E R R  
  13.  *              *****************             
  14.  *                                
  15.  *                 Written by                   
  16.  *               Brian Siritzky              
  17.  *                1983                 
  18.  *                                
  19.  ********************************************************************/
  20.  
  21. /********************************************************************/
  22.  
  23. /********************************************************************/
  24.  
  25. #include "hdr.h"
  26. #include "ada.h"
  27. #include "adalexp.h"
  28. #include "actionp.h"
  29. #include "pspansp.h"
  30. #include "errsp.h"
  31. #include "lookupp.h"
  32. #include "prsutilp.h"
  33. #include "recoverp.h"
  34. #include "makecorp.h"
  35. #include "prserrp.h"
  36.  
  37. static void get_poss_tok();
  38. static void get_next(int);
  39.  
  40. /*    
  41.  * Variables needed for scope and secondary recoveries
  42.  */
  43.  
  44. struct two_pool *closer_toksyms ;
  45. struct two_pool *closer_bottom ;
  46.  
  47. struct two_pool *POSS_TOK;
  48. /* struct prsstack **tokens; deleted on Sam's suggestion 12-11-84 */
  49. int    TOKSYMS[S_TOKSYMS], n_TOKSYMS;
  50. int    BACKUPTOKS = 0;
  51. int    MAX_CHECK = MIN_LEN ;
  52.  
  53. PCAND next_c, y, next_cand, CANDIDATES[C_BOUND];
  54. static PCAND tmp_cand,temp_cand;
  55. int    n_CANDIDATES[C_BOUND] ;
  56. int nps;
  57. int n_open_seq;
  58. int *open_seq;
  59. int n_closer_toksyms;
  60.  
  61. void prserr(struct prsstack *curtok)                            /*;prserr*/
  62. {
  63.  
  64.     /********************************************************************
  65.      *
  66.      * This routine is the syntactic error    recovery  routine.   It     at-
  67.      * tempts  to  correct    simple errors and when that is not possible,
  68.      * deletes tokens possibly to the left and to the right of the error
  69.      * point until the parse can safely resume.  The process is thus di-
  70.      * vided naturally into two  parts,  called  primary  and  secondary
  71.      * recovery.  Both primary and secondary recovery include efforts at
  72.      * "scope recovery": i.e.  the    closing     of  lexically    open  scopes
  73.      * through the insertion of one or more closer token sequences.     Ex-
  74.      * amples of such sequences are right parentheses, "END ;", and "END
  75.      * IF;".
  76.      * 
  77.      * Primary recovery consists of the simple corrections - merging to-
  78.      * kens,  substituting    a  token  (including a reserved word that is
  79.      * misspelled as an identifier), inserting a token, and     deleting  a
  80.      * token - along with scope recovery.
  81.      * 
  82.      * An attempt at simple correction at either the error token  or  at
  83.      * some parse stack element is called a trial.
  84.      * 
  85.      * For the first trial simple corrections are attempted at the token
  86.      * at which the error was detected (the error token), with the parse
  87.      * in the configuration obtaining just after  the  shifting  of     the
  88.      * previous  token. In order to back up to the succeeding trial, the
  89.      * top elements are peeled from the state and parse stacks, with the
  90.      * top element of the parse stack appended to the front of the input
  91.      * token sequence. Again attempts at simple correction are made. The
  92.      * process  is    repeated  until     the determined extent of the backup
  93.      * move has been accomplished.
  94.      * 
  95.      * The criterion by which the effectiveness of a  simple  correction
  96.      * candidate is measured is the distance it allows the parse to pro-
  97.      * gress into the forward context (up to  MAX_LOOK_AHEAD  =  25     to-
  98.      * kens).   During  the     simple correction trials we gather together
  99.      * the CANDIDATES that allow the parse    to  progress  the  furthest,
  100.      * provided  that  an  advance of at least MIN_CHECK is accomplished
  101.      * (if not, then CANDIDATES is empty and simple     correction  fails).
  102.      * If  CANDIDATES is not empty, it is pruned in accordance with cer-
  103.      * tain restrictions described below, and then one of them is chosen
  104.      * as the appropriate correction provided that a condition described
  105.      * below is satisfied.
  106.      * 
  107.      * No attempt is made to delete or substitute for a nonterminal.
  108.      * 
  109.      * If no simple correction is chosen, scope recovery is attempted at
  110.      * each     point    at  which  simple  recovery was attempted. The scope
  111.      * recovery procedure determines whether the insertion of a sequence
  112.      * of  scope  closers  allows the parse to progress MIN_LEN distance
  113.      * into the forward context.  If  so,  this  multiple  insertion  is
  114.      * chosen as the correction candidate.
  115.      * 
  116.      * If scope recovery also fails, then secondary recovery is invoked.
  117.      * The    parse  is  restored  to the configuration obtaining upon en-
  118.      * trance to PRSERR, and each parse stack element is tested - in se-
  119.      * quence from the top - to see whether parsing can resume from that
  120.      * point, perhaps with the inclusion of one or more closer token se-
  121.      * quences.  The  extent  of  the  advance required in order for the
  122.      * parse to be regarded as successfully     resumed  depends  upon     the
  123.      * current token, but is at least MIN_LEN.
  124.      * 
  125.      * If secondary recovery at the current token does not    succeed,  it
  126.      * is  ignored    and  the next one obtained and the same check is re-
  127.      * peated. Eventually, there must be an input for  which  the  parse
  128.      * can    continue, because the end of file token, EOFT, is compatible
  129.      * with a state on the state stack.
  130.      * 
  131.      * When the recovery point is found,  control  is  returned  to     the
  132.      * parser.  It is assured that parsing can continue beyond the error
  133.      * token.
  134.      * 
  135.      ********************************************************************/
  136.  
  137.     /* PARSE STACK and BINARY TUPLE STRUCTURES */
  138.     typedef struct two_pool *TUPLE;
  139.  
  140.  
  141.     struct prsstack *ERROR_TOKEN;
  142.     struct prsstack *oldprevtok;/* Saved for scope and secondary recovery */
  143.     struct prsstack *tmp_ps;
  144.  
  145.     TUPLE STATE_STACK = NULL;
  146.     TUPLE prs_toks = NULL;    /* Used to determine the no of */
  147.     TUPLE tmp_tp;            /* trials to be performed */
  148.     /* Used for freeing storage */
  149.     TUPLE prs_stack_syms = NULL;
  150.  
  151.     int pb;            /* Used as a flag to check for a parse block */
  152.     int threshold,        /* Used to prune candidates */
  153.     exists;        /* Flag used in list searching */
  154.  
  155.     short trials,        /* Number of trials performed    */
  156.       j, r, trial,
  157.       i,            /* Loop and auxilliary        */
  158.       bk, cc, x, si ;
  159.  
  160.     int n_PARSE_STACK;
  161.     int save_n_TOKSYMS ;
  162.     struct two_pool *states;
  163.  
  164.     int        n_single_cand_modes, total_CANDIDATES;
  165.     int        n_STATE_STACK, n_sta_stack;
  166.  
  167.     ERROR_TOKEN = copytoken (curtok);
  168.     MAX_CHECK = MIN_LEN;
  169.  
  170.     /* ERR_MSGS = NULL ; CLOSER_TOKSYMS = NULL ; */
  171.  
  172.     copystack (sta_stack, &STATE_STACK, &n_sta_stack);
  173.     /* save for scope and secondary recovery */
  174.     if (PREVTOK != NULL)
  175.         oldprevtok = copytoken (PREVTOK);
  176.  
  177.     n_STATE_STACK = n_sta_stack;
  178.  
  179.     BACKUPTOKS = 0;
  180.  
  181.     get_next (MAX_LOOK_AHEAD);
  182.  
  183.     /* prs_stack_syms := [r(1) : r in PRS_STACK];            
  184.      * Loop over PRS_STACK, collecting the symbols in a list  
  185.      * headed by prs_stack_syms. While doing this, count up the 
  186.      * number of elements in the parse stack, keeping this in  
  187.      * n_PARSE_STACK and nps                   
  188.      */
  189.  
  190.     n_PARSE_STACK = 0;
  191.  
  192.     if ((tmp_ps= prs_stack) == NULL)/* Check for empty stacks */
  193.         prs_stack_syms = NULL;
  194.     else {                /* otherwise copy the list */
  195.         /* Treat the first element as a special case */
  196.         tmp_tp = prs_stack_syms = TALLOC ();
  197.         tmp_tp -> link = NULL;
  198.         tmp_tp -> val.state = tmp_ps -> symbol;
  199.         n_PARSE_STACK = 1;
  200.         /* Loop over the rest of the stack */
  201.         while (tmp_ps -> prev != NULL) {
  202.             tmp_tp -> link = TALLOC ();
  203.             tmp_tp = tmp_tp -> link;
  204.             tmp_ps = tmp_ps -> prev;
  205.             tmp_tp -> val.state = tmp_ps -> symbol;
  206.             n_PARSE_STACK++;
  207.         }            /* while */
  208.         tmp_tp -> link = NULL;
  209.     }                /* else */
  210.     nps = n_PARSE_STACK;
  211.  
  212.     /* * TOKSYMS := [t(1) : t in TOKENS];             
  213.      * Loop over TOKENS, collecting the symbols in a list    
  214.      * The integer tokind is a count of the number of     
  215.      * elements in the array tokens.              
  216.      *
  217.      * Note that tokens[tokind] is the next token, so we must
  218.      * reverse the order of TOKSYMS                            
  219.      */
  220.  
  221.     /* Put the current token at the top of the token stack */
  222.     tokens[tokind = (tokind + 1) % toksiz] = curtok;
  223.     i = 0;
  224.     j = tokbottom;
  225.  
  226.     for (;;) {
  227.         TOKSYMS[i] = tokens[j]->symbol;
  228.         if (j == tokind)
  229.             break;
  230.         j = (j + 1) % toksiz;
  231.         i++;
  232.     }
  233.  
  234.     save_n_TOKSYMS    = n_TOKSYMS = (toksiz + tokind - tokbottom) % toksiz;
  235.     /*
  236.     for (i = 0; i <= tokind; i++)
  237.     TOKSYMS[i] = tokens[i] -> symbol;
  238.  
  239.     n_TOKSYMS = tokind;
  240.     */
  241.     dump_toksyms ("At creation");
  242.  
  243.     /******************************************************************* 
  244.      *
  245.      *                    S I M P L E    R E C O V E R Y            
  246.      *           
  247.      *******************************************************************/
  248.  
  249.     /*    Simple Recovery begins here     */
  250.  
  251.     /* Determine number of trials to be performed.  */
  252.     prs_toks = TALLOC ();
  253.     prs_toks -> val.state = curtok -> symbol;
  254.     prs_toks -> link = NULL;
  255.  
  256.     /* trials = (nps>0) ? nps : 1 ; */
  257.     trials = (n_sta_stack>0) ? n_sta_stack : 1 ;
  258.  
  259.     states = TALLOC ();
  260.     states -> link = NULL;
  261.  
  262.     /* for (j = nps; j >= 1; j--) */
  263.     for (j = n_sta_stack; j >= 2; j--) {
  264.         int    jj;
  265.         /* prs_stack_syms(j) is at position (nps - j)  in the linked list.
  266.          * For this reason we need to follow the links this many times
  267.          */
  268.         /* jj = nps - j + 1; */
  269.         jj = n_sta_stack - j + 1;
  270.         tmp_tp = prs_stack_syms;
  271.         while (jj-- > 1)
  272.             tmp_tp = tmp_tp -> link;
  273.  
  274.         r = tmp_tp -> val.state;    /* r := prs_stack_syms(j) */
  275.  
  276. #ifdef DEBUG
  277.         if (trcopt) {
  278.             fprintf(errfile,"j = %d     n_sta_stack = %d  r = %d\n",
  279.               j,n_sta_stack,r);
  280.         }
  281. #endif
  282.         /* dump_stack(prs_toks); */
  283.  
  284.         /* Check whether it is possible to parse past symbol
  285.          *    and through the error token.            
  286.          *
  287.          *    if forall s in SHIFT_STATES(r) | prs_block(s, prs_toks)
  288.          *    then
  289.          *        trials := nps - j + (if is_terminal(r) then 2 else 1 end);
  290.          *        quit;
  291.          *    end if;
  292.          */
  293.         pb = TRUE;        /* Assume that the parse will block */
  294.         /* Loop through SHIFT_STATES(r). This is the array SHIFT_STATES from
  295.          * position SHIFT_STATE_INDEX(r-1) to SHIFT_STATE_INDEX(r) - 1
  296.          * Each time check if the parse blocks, pb. If it does not then end the
  297.          * testing.
  298.          */
  299.         for (si = SHIFT_STATE_INDEX[r - 1];
  300.           ((si <= (SHIFT_STATE_INDEX[r] - 1)) && pb);
  301.           si++)
  302.         {
  303.             states -> val.state = SHIFT_STATE[si];
  304.             pb = pb && prs_block (states, prs_toks);
  305.  
  306. #ifdef DEBUG
  307.             if (trcopt)
  308.                 fprintf(errfile,"state: %d     prsblock: %d\n",
  309.                   states->val.state, prs_block(states,prs_toks) );
  310. #endif
  311.         }
  312.  
  313.         if (pb) {            /*  If the parse blocks then terminate    */
  314.             /*trials = 1 + nps - j + (is_terminal (r - 1) ? 2 : 1);*/
  315.             trials = 1 + n_sta_stack - j + (is_terminal (r) ? 2 : 1);
  316.             break;        /* Outer loop */
  317.         }
  318.  
  319.         tmp_tp = TALLOC ();
  320.         tmp_tp -> link = prs_toks;
  321.         tmp_tp -> val.state = r;
  322.         prs_toks = tmp_tp;
  323.  
  324.     }                /* end for */
  325.  
  326.     if (nps == 0)
  327.         trials = 1;    /* To deal with empty parse stacks */
  328. #ifdef DEBUG
  329.     if (trcopt)
  330.         fprintf(errfile,"trials = %d\n",trials);
  331. #endif
  332.  
  333.     for (trial = 1; trial <= trials; trial++) {
  334.         /*    Attempt simple recovery at token backed up to.     */
  335. #ifdef DEBUG
  336.         if (trcopt) {
  337.             fprintf(errfile,"Backup Recovery, trial number is: %d\n",trial);
  338.             fprintf(errfile,"STATE STACK:\n");
  339.             dump_stack(sta_stack);
  340.             fprintf(errfile,"PARSE STACK:\n");
  341.             dump_prssyms(prs_stack_syms);
  342.             fprintf(errfile,"TOKENS:\n");
  343.             dump_toksyms("");
  344.         }
  345. #endif
  346.  
  347.         /* Form set of candidates for insertion and substitution. */
  348.  
  349.         get_poss_tok ();
  350.  
  351.         /* Make insertion test.   */
  352.  
  353.         try_insertion ();
  354.  
  355.         /* Attempt substitution for current token */
  356.  
  357.         try_substitution ();
  358.  
  359.         /* Try merging tokens. */
  360.  
  361.         if (trial == 1)
  362.             try_merge (curtok, nexttok);
  363.         else
  364.             if (trial == 2)
  365.                 try_merge (PREVTOK, curtok);
  366.  
  367.         /* Check whether parsing can resume with the next token. */
  368.  
  369.         try_deletion ();
  370.  
  371.         /* Now we peel off the top state and try again.           
  372.          * Put the "token" (terminal or nonterminal) for previous state on 
  373.          * the list of tokens, and increase backuptoks accordingly.       
  374.          */
  375.  
  376.         tmp_tp = sta_stack;
  377.         sta_stack = sta_stack -> link;
  378.         n_sta_stack--;
  379.  
  380.         tmp_tp = prs_stack_syms;
  381.         if (prs_stack != NULL) {
  382.             TOKSYMS[++n_TOKSYMS] = prs_stack_syms -> val.state;
  383.             prs_stack_syms = prs_stack_syms -> link;
  384.         }
  385.         BACKUPTOKS++;
  386.  
  387.     }                /* for */
  388.  
  389.  
  390.     /* Form misspelling candidates by applying string distance test in cases
  391.      *   where a reserved word to be substituted for an identifier.     
  392.      */
  393.  
  394.     if (0 && CANDIDATES[SUBST] != NULL) {
  395. #ifdef DEBUG
  396.         if (trcopt)
  397.             fprintf (errfile, "CANDIDATES[SUBST] != NULL, (#=%d)\n",
  398.                 n_CANDIDATES[SUBST]);
  399. #endif
  400.         /*  spell_substs := {[u, v, w] in CANDIDATES(SUBST) |
  401.          *         is_reserved(u) and v = ID_SYM 
  402.          *        and spell(namelist(u), namelist(
  403.          *         (w = 0 ? curtok : PRS_STACK(nps - w + 1) )(2)))};
  404.          *
  405.          *   Note : u == token_sym, v == backup_toks, w == t3
  406.          *
  407.          *   Loop over the list headed by CANDIDATES[SUBST], selecting
  408.          *  all those elements which satisfy the above conditions
  409.          *
  410.          *    The spell function used here is a less accurate measure than the
  411.          *  SETL version. It returns an integer value in the range [0,3],
  412.          *  where 0, 1 & 2 imply misspellings.
  413.          */
  414.         nps = stack_count(prs_stack) ;
  415.         next_c = CANDIDATES[SUBST];
  416.         while (next_c != NULL) {
  417.             short   symb;    /* Utility variable */
  418.             PCAND    follow_c ;
  419.  
  420.             follow_c = next_c-> next ;
  421.  
  422.             /* Calculate the word to be compared to according to
  423.              *        symb = (w==0)?curtok : prs_stack(nps -w + 1)
  424.              */
  425.  
  426.             if (next_c -> backup_toks == 0)
  427.                 symb = curtok -> symbol;
  428.             else {            /* PRSSTACK[nps-w-1].symbol */
  429.                 int kk = nps - next_c->backup_toks ;
  430.  
  431.                 tmp_ps = prs_stack;
  432.                 while(--kk)
  433.                     tmp_ps = tmp_ps -> prev;
  434.                 symb = tmp_ps -> symbol;
  435.             }
  436.  
  437.             if ( (is_reserved (next_c -> token_sym))
  438.               && (next_c -> t3 == ID_SYM)
  439.               && ((spell (TOKSTR (next_c -> token_sym), TOKSTR (symb))) < 3 ) )
  440.             {
  441.                 /* Add it to the list of SPELL_SUBSTs. */
  442.  
  443.                 next_c-> next = CANDIDATES[SPELL_SUBST] ;
  444.                 CANDIDATES[SPELL_SUBST] = next_c ;
  445.                 n_CANDIDATES[SPELL_SUBST]++;
  446.                 n_CANDIDATES[SUBST]--;
  447.             }
  448.  
  449.             next_c = follow_c ;
  450.         }
  451.  
  452.     }
  453. #ifdef DEBUG
  454.     if (trcopt) {
  455.         fprintf(errfile,"Candidates BEFORE pruning\n");
  456.         dump_cand();
  457.     }
  458. #endif
  459.  
  460.     /* The correction candidates now include only those that have checked
  461.      * the furthest distance into the forward context.
  462.      * Prune this set by applying the preferences and restrictions relevant 
  463.      * in each case.
  464.      */
  465.  
  466.     /* If a long parse check has been achieved, set threshold to true.  */
  467.  
  468.     threshold = (MAX_CHECK >= (MIN_LEN + 3));
  469.  
  470.     /*  (for y = CANDIDATES(x)) */
  471.  
  472.     for (x = DELETE; x <= SPELL_SUBST; x++)
  473.     {
  474.         y = CANDIDATES[x];
  475.  
  476.         if (y == NULL)        /* Check for null candidate list */
  477.             continue;
  478.  
  479.         switch (x) {
  480.  
  481.         case DELETE:
  482.  
  483.             /* Remove all reserved word deletions if another deletion exists
  484.              * and all such deletions if below the threshold            
  485.              */
  486.  
  487.             next_cand = CANDIDATES[DELETE];
  488.             exists = FALSE;
  489.             while ((next_cand != NULL) && (!exists)) {
  490.                 exists = exists && (next_cand -> token_sym > RESERVED_SYMS);
  491.                 next_cand = next_cand -> next;
  492.             }
  493.  
  494.             if ((!threshold) || exists) {
  495.                 /*  y -:= {[token_sym,-,-] in y | is_reserved(token_sym) }
  496.                  *  This is achieved by looping over the list headed by y
  497.                  *  and deleting those elements which satisfy the condition 
  498.                  */
  499.                 next_cand = CANDIDATES[x];
  500.                 n_CANDIDATES[x] = 0;
  501.                 CANDIDATES[x] = NULL;
  502.                 while (next_cand != NULL) {
  503.                     /* there are more candidates */
  504.                     tmp_cand = next_cand -> next;
  505.                     if (!is_reserved (next_cand -> token_sym)) {
  506.                         /* Add it to the front of the list  */
  507.                         n_CANDIDATES[x]++;
  508.                         next_cand -> next = CANDIDATES[x];
  509.                         CANDIDATES[x] = next_cand;
  510.                     }
  511.                     next_cand = tmp_cand;
  512.                 }
  513.             }
  514.  
  515.             /* Prefer deletion closest to error token.    */
  516.  
  517.             if (y != NULL) {
  518.                 /* bk := min/{t(2) : t in y}; */
  519.                 next_cand = y;
  520.                 bk = next_cand -> backup_toks;
  521.                 next_cand = next_cand -> next;
  522.                 while (next_cand != NULL) {
  523.                     bk = MIN (bk, next_cand -> backup_toks);
  524.                     next_cand = next_cand -> next;
  525.                 }
  526.  
  527.                 n_CANDIDATES[x] = 0;
  528.                 next_cand = CANDIDATES[x];
  529.                 CANDIDATES[x] = NULL;
  530.                 while (next_cand != NULL) {
  531.                     /* there are more candidates */
  532.                     tmp_cand = next_cand -> next;
  533.                     if (next_cand -> backup_toks == bk) {
  534.                         next_cand -> next = CANDIDATES[x];
  535.                         CANDIDATES[x] = next_cand;
  536.                         n_CANDIDATES[x]++;
  537.                     }
  538.  
  539.                     next_cand = tmp_cand;
  540.                 }
  541.             }
  542.             break;
  543.  
  544.         case INSERT:
  545.  
  546.             /* Remove all insertions of reserved words if below threshold */
  547.  
  548.             if (!threshold) {
  549.                 /* y -:= {[token_sym,-,-] in y | is_reserved(token_sym) }     
  550.                  * This is achieved by looping over the list headed by y   
  551.                  * and deleting those elements which satisfy the condition 
  552.                  */
  553.                 n_CANDIDATES[x] = 0;
  554.                 next_cand = CANDIDATES[x];
  555.                 CANDIDATES[x] = NULL;
  556.                 while (next_cand != NULL) {
  557.                     /* there are more candidates */
  558.                     tmp_cand = next_cand -> next;
  559.                     if (!is_reserved (next_cand -> token_sym)) {
  560.                         next_cand -> next = CANDIDATES[x];
  561.                         CANDIDATES[x] = next_cand;
  562.                         n_CANDIDATES[x]++;
  563.                     }
  564.                     next_cand = tmp_cand;
  565.                 }
  566.             }
  567.  
  568.             /* Prefer insertions closest to error token. */
  569.  
  570.             if (CANDIDATES[x] != NULL) {
  571.                 /* bk := min/{t(3) : t in y}; */
  572.                 next_cand = y;
  573.                 bk = next_cand -> backup_toks;
  574.                 next_cand = next_cand -> next;
  575.                 while (next_cand != NULL) {
  576.                     bk = MIN (bk, next_cand -> backup_toks);
  577.                     next_cand = next_cand -> next;
  578.                 }
  579.                 /* y := {[-,backup_toks,-] in y | backup_toks = bk) }       
  580.                  *
  581.                  * This is achieved by looping over the list headed by y   
  582.                  * and deleting those elements which satisfy the condition
  583.                  * While doing this, check if there are any elements  that 
  584.                  * satisfy the condition            
  585.                  *        (token_sym in ALWAYS_PREFERRED_SYMS) 
  586.                  * If there are any they can be used to further prune the  
  587.                  * list. A flag 'exists' will be used for this purpose.
  588.                  */
  589.  
  590.                 n_CANDIDATES[x] = 0;
  591.                 next_cand = CANDIDATES[x];
  592.                 CANDIDATES[x] = NULL;
  593.                 exists = FALSE;
  594.                 /* Assume none in ALWAYS_PREFERRED_SYMS */
  595.                 while (next_cand != NULL) {
  596.                     /* there are more candidates */
  597.                     tmp_cand = next_cand -> next;
  598.                     if (next_cand -> backup_toks == bk) {
  599.                         exists = exists
  600.                           || in_ALWAYS_PREFERRED_SYMS (next_cand -> token_sym);
  601.                         next_cand -> next = CANDIDATES[x];
  602.                         CANDIDATES[x] = next_cand;
  603.                         n_CANDIDATES[x]++;
  604.                     }
  605.                     next_cand = tmp_cand;
  606.                 }
  607.             }
  608.  
  609.             /*     Apply preferred insertions (if any exist)
  610.              *
  611.              *    pi := {[u, v, w] in y | u in ALWAYS_PREFERRED_SYMS};
  612.              *    if (pi != {}) y = pi;
  613.              */
  614.  
  615.             if (exists) {        /* then prune the list accordingly */
  616.                 /* y := {[token_sym,-,-] in y | token_sym in              
  617.                  *        ALWAYS_PREFERRED_SYMS }               
  618.                  * This is achieved by looping over the list headed by y    
  619.                  * and deleting those elements which satisfy the condition  
  620.                  */
  621.  
  622.                 n_CANDIDATES[x] = 0;
  623.                 next_cand = CANDIDATES[x];
  624.                 CANDIDATES[x] = NULL;
  625.                 while (next_cand != NULL) {
  626.                     /* there are more candidates */
  627.                     tmp_cand = next_cand -> next;
  628.                     if (in_ALWAYS_PREFERRED_SYMS (next_cand -> token_sym)) {
  629.                         next_cand -> next = CANDIDATES[x];
  630.                         CANDIDATES[x] = next_cand;
  631.                         n_CANDIDATES[x]++;
  632.                     }
  633.                     next_cand = tmp_cand;
  634.                 }
  635.             }
  636.             break;
  637.  
  638.         case SUBST:
  639.  
  640.             /*         Apply preferred substitutions 
  641.              * 
  642.              *    Check to see whether there are any elements which satisfy   
  643.              *    either of the conditions        
  644.              *            token_sym in PREFERRED_FOR_SYMS{v}
  645.              *           or    token_sym = ID_SYM and is_reserved(v) 
  646.              *    If at least one is found then set y to be ps, where ps is   
  647.              *
  648.              *        ps := {[u, v, w] in y | u in PREFERRED_FOR_SYMS{v}    
  649.              *                or (u = ID_SYM and is_reserved(v))};        
  650.              *
  651.              *    This is achieved by looping over the list headed by y    
  652.              *    and deleting those elements which satisfy the condition
  653.              */
  654.  
  655.             /* check for existence */
  656.  
  657.             next_cand = CANDIDATES[x];
  658.             exists = FALSE; /* Assume none */
  659.             while ((next_cand != NULL) && (!exists)) {
  660.                 /* there are more candidates */
  661.                 exists = exists
  662.                   || in_PREFERRED_FOR_SYMS( next_cand -> t3,
  663.                    next_cand -> token_sym)
  664.                   || ((next_cand -> token_sym == ID_SYM)
  665.                   && (is_reserved (next_cand -> t3)));
  666.                 next_cand = next_cand -> next;
  667.             }
  668.  
  669.             /* If some exist then y is set to be those only */
  670.  
  671.             if (exists) {
  672.                 n_CANDIDATES[x] = 0;
  673.                 next_cand = CANDIDATES[x];
  674.                 CANDIDATES[x] = NULL;
  675.                 while (next_cand != NULL) {
  676.                     /* there are more candidates */
  677.                     temp_cand = next_cand -> next;
  678.                     if ( in_PREFERRED_FOR_SYMS( next_cand -> t3,
  679.                       next_cand -> token_sym )
  680.                       || ((next_cand -> token_sym == ID_SYM)
  681.                       && is_reserved (next_cand -> t3)))
  682.                     {
  683.                         next_cand -> next = CANDIDATES[x];
  684.                         CANDIDATES[x] = next_cand;
  685.                         n_CANDIDATES[x]++;
  686.                     }
  687.                     next_cand = temp_cand;
  688.                 }
  689.             }
  690.             else if (!threshold) {        /* None exist */
  691.                 /* Remove all substitutions involving reserved words if below    
  692.                  * the threshold.                        
  693.                  */
  694.                 /* y -:= {[u, v, w] in y |    
  695.                      *             is_reserved(u) or is_reserved(v)};  
  696.                  */
  697.  
  698.                 n_CANDIDATES[x] = 0;
  699.                 next_cand = CANDIDATES[x];
  700.                 CANDIDATES[x] = NULL;
  701.                 while (next_cand != NULL) {
  702.                     temp_cand = next_cand -> next;
  703.                     if (!((is_reserved (next_cand -> t3))
  704.                       || (is_reserved (next_cand -> token_sym))) )
  705.                     {
  706.                         next_cand -> next = CANDIDATES[x];
  707.                         CANDIDATES[x] = next_cand;
  708.                         n_CANDIDATES[x]++;
  709.                     }
  710.                     next_cand = temp_cand;
  711.                 }
  712.             }
  713.  
  714.             /* Prefer substitutions closest to error token. */
  715.  
  716.             if (CANDIDATES[x] != NULL) {
  717.                 /* bk := min/{t(3) : t in y}; */
  718.                 next_cand = y;
  719.                 bk = next_cand -> backup_toks;
  720.                 next_cand = next_cand -> next;
  721.                 while (next_cand != NULL) {
  722.                     bk = MIN (bk, next_cand -> backup_toks);
  723.                     next_cand = next_cand -> next;
  724.                 }
  725.  
  726.                 n_CANDIDATES[x] = 0;
  727.                 next_cand = CANDIDATES[x];
  728.                 CANDIDATES[x] = NULL;
  729.                 while (next_cand != NULL) {
  730.                     /* there are more candidates */
  731.                     temp_cand = next_cand -> next;
  732.                     if (next_cand -> backup_toks == bk) {
  733.                         next_cand -> next = CANDIDATES[x];
  734.                         CANDIDATES[x] = next_cand;
  735.                         n_CANDIDATES[x]++;
  736.                     }
  737.                     next_cand = temp_cand;
  738.                 }
  739.             }
  740.             break;
  741.  
  742.         case SPELL_SUBST:
  743.  
  744.             /* Prefer closest to error token. */
  745.  
  746.             /* bk := min/{t(3) : t in y}; */
  747.  
  748.             next_cand = y;
  749.             bk = next_cand -> backup_toks;
  750.             next_cand = next_cand -> next;
  751.             while (next_cand != NULL) {
  752.                 bk = MIN (bk, next_cand -> backup_toks);
  753.                 next_cand = next_cand -> next;
  754.             }
  755.  
  756.             /*         y := {[-,-,t3] in y | t3=bk }            
  757.              * This is achieved by looping over the list headed by y   
  758.              * and deleting those elements which satisfy the condition 
  759.              */
  760.  
  761.             if (CANDIDATES[x] != NULL) {
  762.                 n_CANDIDATES[x] = 0;
  763.                 next_cand = CANDIDATES[x];
  764.                 CANDIDATES[x] = NULL;
  765.                 while (next_cand != NULL) {
  766.                     /* there are more candidates */
  767.                     temp_cand = next_cand -> next;
  768.                     if (next_cand -> backup_toks == bk) {
  769.                         next_cand -> next = CANDIDATES[x];
  770.                         CANDIDATES[x] = next_cand;
  771.                         n_CANDIDATES[x]--;
  772.                     }
  773.                     next_cand = temp_cand;
  774.                 }
  775.             }
  776.             break;
  777.  
  778.         case MERGE:
  779.  
  780.             break;
  781.  
  782.         }            /* switch */
  783.  
  784.     }                /* for */
  785. #ifdef DEBUG
  786.     if (trcopt) {
  787.         fprintf(errfile,"Candidates AFTER pruning:\n");
  788.         dump_cand();
  789.     }
  790. #endif
  791.  
  792.  
  793.     /* For each mode - merge, spelling, insertion, substitution, deletion -
  794.      * there are zero or more correction candidates.  
  795.      * If one or mode has exactly one correction candidate, then one of those
  796.      * candidates is chosen.
  797.      * 
  798.      * If no mode has a single candidate, then a simple correction candidate 
  799.      * is only chosen if the long check distance has been achieved 
  800.      *            (MAX_CHECK >= MIN_LEN + 3).
  801.      * 
  802.      * The preference order among the correction modes is : merge, spelling,
  803.      * insertion, deletion, substitution.
  804.      */
  805.  
  806.     /* Calculate the number of single_cand_modes     */
  807.     /* and the total number of CANDIDATES         */
  808.  
  809.     n_single_cand_modes = 0;
  810.     total_CANDIDATES = 0;
  811.  
  812.     for (cc = DELETE; cc <= SPELL_SUBST; cc++) {
  813.         if (n_CANDIDATES[cc] == 1)
  814.             n_single_cand_modes++;
  815.         total_CANDIDATES += n_CANDIDATES[cc];
  816.     }
  817.  
  818.     if (n_single_cand_modes > 0) {
  819.         /* Apply one final preference rule where there remains a single 
  820.          *    deletion and a single insertion candidate - prefer deletion of 
  821.          *    operator or punctuation symbol to insertion of such a symbol.  
  822.          */
  823.         if ((n_CANDIDATES[DELETE] == 1)
  824.           && ((n_CANDIDATES[INSERT]) == 1)
  825.           && is_operator (CANDIDATES[DELETE] -> token_sym)
  826.           && is_operator (CANDIDATES[INSERT] -> token_sym))
  827.         {
  828.             /* Set CANDIDATES[INSERT] to NULL and dispose of the list */
  829.             CANDIDATES[INSERT] = NULL;
  830.             n_CANDIDATES[INSERT] = 0;
  831.             n_single_cand_modes--;
  832.             total_CANDIDATES--;
  833.         }
  834.  
  835.         /* Set all CANDIDATES which have more than 1 element to NULL    
  836.          * and dispose of their lists                        
  837.          */
  838.  
  839.         for (cc = DELETE; cc <= SPELL_SUBST; cc++)
  840.             if (n_CANDIDATES[cc] > 1) {
  841.                 CANDIDATES[cc] = NULL;
  842.                 n_CANDIDATES[cc] = 0;
  843.             }
  844.  
  845.     }                /* if */
  846.  
  847.     if ((n_single_cand_modes > 0) || ((total_CANDIDATES > 0) && threshold)) {
  848.         make_correction (STATE_STACK);
  849.         return;
  850.     }
  851.  
  852.     /*  Primary recovery has failed if we reach this point. 
  853.      *  Reset parse configuration for scope recovery.    
  854.      */
  855.  
  856.     copystack (STATE_STACK, &sta_stack, &n_STATE_STACK);
  857.     /*  TOKSYMS(n_TOKENS + 1 .. ) := []; */
  858.     n_TOKSYMS = save_n_TOKSYMS ;
  859.     BACKUPTOKS = 0;
  860.  
  861.     /************************************************************************
  862.      *                                      
  863.      *        E N D     O F     P R I M A R Y    R E C O V E R Y           
  864.      *                                    
  865.     ************************************************************************/
  866.  
  867.     /************************************************************************
  868.      *                                      
  869.      *                    Scope recovery 
  870.      *                                    
  871.     ************************************************************************/
  872.  
  873.     /* SCOPE */
  874.     {
  875.  
  876.         int     j;
  877.         struct prsstack *prstmp;
  878.         struct two_pool *tuptmp;
  879.         struct two_pool *statmp;
  880.         Span_s *prev_tok_loc;
  881.         /* struct tok_loc *prev_tok_loc = &PREVTOK->ptr.token->span; */
  882.  
  883.         if (PREVTOK != NULL)
  884.             prev_tok_loc = &PREVTOK->ptr.token->span;
  885.  
  886.         /*    Allocate an array the size of the parse stack */
  887.         open_seq = (int *)malloc((unsigned) (nps * sizeof(int)));
  888.  
  889. #ifdef DEBUG
  890.         if (trcopt)
  891.             fprintf(errfile,"SCOPE OPENERS = \n");
  892. #endif
  893.         for (n_open_seq = 0,j = nps, prstmp = prs_stack; prstmp != NULL;
  894.           prstmp = prstmp->prev, j--) {
  895.             if (is_opener(prstmp->symbol)) {
  896.                 open_seq[n_open_seq++] = j;
  897. #ifdef DEBUG
  898.                 if (trcopt)
  899.                     fprintf(errfile,"[ %s %d ] ",TOKSTR(prstmp->symbol),j);
  900. #endif
  901.             }
  902.         }
  903. #ifdef DEBUG
  904.         if (trcopt)
  905.             fprintf(errfile,"\n");
  906. #endif
  907.  
  908.         /* for debugging purposes try one less trial */
  909.         trials-- ;
  910.  
  911.  
  912.         closer_toksyms = NULL;
  913.         closer_bottom = NULL;
  914.  
  915.         for (trial = 1 ; trial <= trials ; trial ++ ) {
  916. #ifdef DEBUG
  917.             if (trcopt)
  918.                 fprintf(errfile,"Scope Recovery Trial = %d\n",trial);
  919. #endif
  920.             if (scope_recovery(n_STATE_STACK,0,open_seq)) {
  921.                 for (tuptmp = closer_toksyms; tuptmp != NULL;
  922.                   tuptmp = tuptmp->link)
  923.                 {
  924.                     prstmp = PRSALLOC();
  925.                     prstmp->ptr.token = TOKALLOC();
  926.                     prstmp->symbol =prstmp->ptr.token->index =tuptmp->val.state;
  927.                     prstmp->ptr.token->span.line = prev_tok_loc->line;
  928.                     prstmp->ptr.token->span.col = prev_tok_loc->col;
  929.                     add_to_top(prstmp);
  930.                 }
  931.                 /* if (closer_toksyms != NULL)
  932.                  * TFREE(closer_toksyms,closer_bottom);
  933.                  */
  934.                 n_closer_toksyms = 0 ;
  935.                 return;
  936.             }
  937.             /* if (closer_toksyms != NULL)
  938.              *    TFREE(closer_toksyms,closer_bottom);
  939.              */
  940.             n_closer_toksyms = 0 ;
  941.             /*    Back up for the next trial */
  942.  
  943.             if (trial == trials)
  944.                 break;
  945.  
  946.             statmp = sta_stack;
  947.             sta_stack = sta_stack->link;
  948.             TFREE(statmp,statmp);
  949.             n_STATE_STACK -- ;
  950.  
  951.             prstmp = prs_stack;
  952.             prs_stack = prs_stack->prev;
  953.             nps-- ;
  954.  
  955.             add_to_top(prstmp);
  956.  
  957.             TOKSYMS[++n_TOKSYMS] = prstmp->symbol;
  958.  
  959.             BACKUPTOKS++;
  960.  
  961.             prev_tok_loc = RLOC(prs_stack);
  962.         }
  963.  
  964.         /*    To get here scope recovery has failed, try other recoveries */
  965.  
  966.         /*  First restore the parse configuration for secondary recovery */
  967.         copystack(STATE_STACK,&sta_stack,&n_sta_stack) ;
  968.  
  969.         for (trial = 1 ; trial < trials ; trial ++) {
  970.             struct prsstack *tmp_ps ;
  971.  
  972.             tmp_ps = tokens[tokind];
  973.             n_TOKSYMS -- ;
  974.             TOKMINUS ;
  975.             tmp_ps->prev = prs_stack ;
  976.             prs_stack = tmp_ps ;
  977.             nps ++ ;
  978.         }
  979.  
  980.         PREVTOK = oldprevtok ;
  981.         BACKUPTOKS = 0 ;
  982.     }
  983.  
  984.     /************************************************************************
  985.      *                                      
  986.      *                    Secondary recovery 
  987.      *                                    
  988.      ************************************************************************/
  989.     /*SEC*/
  990.  
  991.     /* Now try secondary recoveries.    
  992.      * First try deleting the error token and some sequence of tokens in the 
  993.      * forward context - stop at a beacon symbol.    
  994.      */
  995.     {
  996. #define sec_check    MIN_LEN
  997.  
  998.         char    tmp_str[500],
  999.         err_msgs[500];
  1000.         int        equal;
  1001.         int        nst;
  1002.         int        n_stack_del_syms;
  1003.         int        t, kk, j, k;
  1004.         int       *stack_delete_syms;
  1005.         Span_s  leftt,
  1006.         rightt;
  1007.  
  1008.         err_msgs[0] = '\0' ; /* initialize to null string */
  1009.  
  1010.         for (k = 1; k <= MAX_LOOK_AHEAD - (MIN_LEN + 3); k++) {
  1011.  
  1012.             t = TOKSYMS[n_TOKSYMS--];
  1013. #ifdef DEBUG
  1014.             if (trcopt)
  1015.                 fprintf (errfile, "take token off TOKSYMS (%s)\n", TOKSTR (t));
  1016. #endif
  1017.  
  1018.             if((kk=prs_check(sta_stack, TOKSYMS, n_TOKSYMS)) >= (MIN_LEN + 3)) {
  1019.                 /* changed +2 to +3, gcs */
  1020.                 /* delete k tokens */
  1021.  
  1022.                 /*    rightt := TOKENS(n_TOKENS - k + 1);
  1023.                  *  TOKENS(n_TOKENS - k + 1 ..) := [];
  1024.                  */
  1025.                 for (i = 1; i < k; i++)
  1026.                     TOKMINUS;
  1027.  
  1028.                 rightt = r_span (tokens[tokind]);
  1029.                 TOKMINUS;
  1030.  
  1031.                 syntax_err (LLOC (ERROR_TOKEN), &rightt, "Unexpected input");
  1032.  
  1033.                 return;
  1034.             }
  1035.  
  1036.             /* For now, ignore to conform with SETL (BEACON_SYMS is empty) 
  1037.              *    if (in_BEACON_SYMS (t))
  1038.               *   break;
  1039.              */
  1040.         }
  1041.  
  1042.         /* Try to resume the parse - perhaps with the inclusion of a sequence of
  1043.          * scope closers-  from some state on the state stack.    
  1044.          * After each attempt the current token is deleted.
  1045.          * To succeed on arbitrary input, some state must accept EOFT.
  1046.          */
  1047.  
  1048. #ifdef DEBUG
  1049.         if (trcopt)
  1050.             fprintf(errfile,"********** SECONDARY RECOVERY **********\n");
  1051. #endif
  1052.  
  1053.         nst = stack_size (sta_stack);
  1054.  
  1055.         while (1) {
  1056.             struct two_pool *sta_stack_copy;
  1057.  
  1058.             get_next(sec_check + 2);     /* ensure that there are ample */
  1059.  
  1060.             /*    TOKSYMS := [t(1) : t in TOKENS]; */
  1061.  
  1062.             i = 0;
  1063.             j = tokbottom;
  1064.  
  1065.             for (;;) {
  1066.                 TOKSYMS[i] = tokens[j] -> symbol;
  1067.                 if (j == tokind)
  1068.                     break;
  1069.                 j = (j + 1) % toksiz;
  1070.                 i++;
  1071.             }
  1072.  
  1073.             n_TOKSYMS = (toksiz + tokind - tokbottom) % toksiz;
  1074.  
  1075.             curtok = tokens[tokind];
  1076.  
  1077. #ifdef DEBUG
  1078.             if (trcopt) {
  1079.                 fprintf(errfile,"TRYING: %s\n",TOKSTR(TOKSYMS[n_TOKSYMS]) );
  1080.                 fprintf(errfile,
  1081.                   "\ttoksize = %d  tokbottom = %d  tokind = %d  curtok = %s\n",
  1082.                   toksiz,tokbottom,tokind,find_name(curtok) );
  1083.             }
  1084. #endif
  1085.  
  1086.             copystack (sta_stack, &sta_stack_copy, &nst);
  1087.  
  1088.             for (k = nst; k >= 1; k--) {
  1089.  
  1090.                 /* Try peeling stacks. */
  1091.  
  1092.                 /* Strip n_sta_stack - k - 1 elements off the state stack */
  1093.  
  1094.                 kk = stack_size (sta_stack_copy) - k;
  1095.  
  1096.                 /* while (--kk > 0)
  1097.                  *  sta_stack_copy = sta_stack_copy -> link;
  1098.                  */
  1099.  
  1100.                 if ( (kk=prs_check (sta_stack_copy, TOKSYMS, n_TOKSYMS)) >=
  1101.                   (sec_check + 2)) { /* (sec_check + 1)) */
  1102.                     /* Form the error message and quit the outer loop */
  1103.                     sprintf (err_msgs, "%s", err_message (k,curtok));
  1104. #ifdef DEBUG
  1105.                     if (trcopt)
  1106.                         fprintf(errfile,"prs_check succeeded for k = %d\n",k);
  1107. #endif
  1108.                     goto quit_loop_do;
  1109.                 }
  1110.  
  1111.                 /* Try closer recovery. */
  1112.  
  1113.                 /* Make a copy of the state stack for later restoration */
  1114.  
  1115.                 if (scope_recovery (k, 0, open_seq)) {
  1116.                     /* Form the error message and quit the outer loop */
  1117.                     sprintf (tmp_str, "%s", err_msgs);
  1118.                     sprintf (err_msgs, "%s -- %s", err_message(k,curtok),
  1119.                       tmp_str);
  1120. #ifdef DEBUG
  1121.                     if (trcopt)
  1122.                         fprintf(errfile,
  1123.                           "scope_recovery succeeded for k = %d\n",k);
  1124. #endif
  1125.  
  1126.                     goto quit_loop_do;
  1127.                 }
  1128.                 /* pop element of the state stack  */
  1129.                 sta_stack_copy = sta_stack_copy -> link;
  1130.  
  1131.                 closer_toksyms = NULL;
  1132.             }
  1133.  
  1134.             /* Get next token */
  1135.  
  1136. #ifdef IGNORE
  1137.             PREVTOK = tokens[tokind];
  1138.             /* This is a fix proposed by Sam Chin for cases when the entire
  1139.              * text is garbage. If there are tokens on the list of lookahead
  1140.              * tokens then take the token, otherwise, if not then take it from
  1141.              * the input stream. If while deleting the tokens an end of file
  1142.              * is reached, output the appropriate message and quit the
  1143.              * secondary recovery
  1144.              */
  1145.             curtok = NEXTTOK ;
  1146. #ifdef DEBUG
  1147.             if (trcopt)
  1148.                 fprintf(errfile,"curtok = %s\n",find_name(curtok));
  1149. #endif
  1150.             if (curtok->symbol == EOFT_SYM) {
  1151.                 sprintf(err_msgs,"End-of-file reached while trying to recover");
  1152.                 goto quit_loop_do ;
  1153.             }
  1154.  
  1155.             if (tokind >= MAX_LOOK_AHEAD) {
  1156.                 curtok = copytoken(tokens[tokind]) ;
  1157. #ifdef DEBUG
  1158.                 if (trcopt)
  1159.                     fprintf(errfile,"curtok updated to  %s\n",
  1160.                       find_name(curtok));
  1161. #endif
  1162.             }
  1163. #endif
  1164.  
  1165.             /* implement next_token macro (correctly), as done in SETL */
  1166.             PREVTOK = curtok;
  1167.             TOKMINUS;
  1168.             if ((toksiz + tokind - tokbottom + 1) % toksiz == 0)
  1169.                 tokens[tokbottom=(toksiz+tokbottom-1)%toksiz] = gettok();
  1170.  
  1171.             /* NEXTTOK; */
  1172.  
  1173.             /* copytoken (curtok, tokens[tokind]); */
  1174.  
  1175.         }
  1176.  
  1177. quit_loop_do: 
  1178.         ;            /* LABEL for goto */
  1179.  
  1180.  
  1181.         /* At this point we have recovered.    
  1182.          * Locate the range of the error.    
  1183.          */
  1184.  
  1185.  
  1186.         n_stack_del_syms = 0;
  1187.         if (nst > k     &&  k > 0  &&    prs_stack != NULL) {
  1188.             /* check for empty parse stack and k not zero (i.e. end of file) */
  1189.  
  1190.             /* stack_delete_syms :=
  1191.                 [PRS_STACK(t)(1) : t in [nps, nps - 1 .. k + 1]]; */
  1192.  
  1193.             /* nps = stack_count (prs_stack); */
  1194.             tmp_ps = prs_stack;
  1195.             stack_delete_syms =
  1196.               (int *) malloc ((unsigned) ((nst - k ) * sizeof (int)));
  1197.             /* stack_delete_syms = (int *) malloc ((k + 1) * sizeof (int)); */
  1198.             for (t = nst; t >= k + 1; t--) {
  1199.                 stack_delete_syms[n_stack_del_syms++] = tmp_ps -> symbol;
  1200.                 tmp_ps = tmp_ps -> prev;
  1201.             }
  1202.  
  1203.             leftt = l_span (tmp_ps);
  1204.  
  1205.             /*         PRS_STACK(k + 1 .. ) := [];
  1206.              *                STA_STACK(k + 1 .. ) := [];    
  1207.              */
  1208.  
  1209.             kk = stack_size (sta_stack) - k;
  1210.             while ( kk-- > 0) {
  1211.                 sta_stack = sta_stack -> link;
  1212.                 prs_stack = prs_stack -> prev;
  1213.             }
  1214.         }
  1215.         else
  1216.             leftt = l_span (ERROR_TOKEN);
  1217.  
  1218.  
  1219.         /* Form error location. */
  1220.  
  1221.         /*
  1222.          *    Check whether 
  1223.          *        stack_delete_syms = 
  1224.          *            TOKSYMS(#TOKSYMS - #stack_del_syms + 1 ..  #stack_del_syms)
  1225.          *
  1226.          *    Assume equal and check element by element
  1227.          */
  1228.  
  1229.         equal = 1;
  1230.         for (j = n_stack_del_syms - 1 , k = n_TOKSYMS ;
  1231.           ((j >= 0) && (equal)) ; k--, j--)
  1232.             equal = equal && (stack_delete_syms[j] == TOKSYMS[k]);
  1233.  
  1234.         if ((n_stack_del_syms != 0) && (n_stack_del_syms <= n_TOKSYMS) && equal)
  1235.         {
  1236.             /* PRSERR_LOC = loc_range(LLOC(ERROR_TOKEN), LLOC(TOKENS[(tokind -
  1237.                 * n_stack_del_syms + 1) % toksiz] ), RLOC(ERROR_TOKEN));
  1238.              * for now just print the spans
  1239.              */
  1240.             syntax_err (LLOC (ERROR_TOKEN), RLOC (ERROR_TOKEN), err_msgs);
  1241.         }
  1242.         else {
  1243.             /* PRSERR_LOC = 
  1244.               *  loc_range(LLOC(leftt), LLOC(PREVTOK), RLOC(ERROR_TOKEN));
  1245.               *  for now just print the spans
  1246.              */
  1247.             syntax_err (&leftt, RLOC (ERROR_TOKEN), err_msgs);
  1248.         }
  1249.  
  1250.         /* If the secondary recovery involves a scope recovery, insert the
  1251.          * closer tokens.    
  1252.          */
  1253.  
  1254.         if (closer_toksyms != NULL) {
  1255.             /* TOKENS +:= [[t, t, top(PREVTOK)] : t in CLOSER_TOKSYMS]; */
  1256.             for(tmp_tp =closer_toksyms; tmp_tp != NULL; tmp_tp = tmp_tp -> link)
  1257.             {
  1258.                 add_to_top (PRSALLOC());
  1259.                 tokens[tokind] -> symbol = tmp_tp -> val.state;
  1260.                 tokens[tokind] -> ptr.token = TOKALLOC ();
  1261.                 tokens[tokind] -> ptr.token -> index = tmp_tp -> val.state;
  1262.                 tokens[tokind] -> ptr.token -> span = PREVTOK -> ptr.token ->span;
  1263.             }
  1264.         }
  1265.  
  1266.         return;
  1267.     }
  1268. }                /* End of Procedure prserr */
  1269.  
  1270. static void get_poss_tok()                    /*;get_poss_tok*/
  1271. {
  1272.     struct two_pool *temp_sta_stack; /* Points to saved copy of state stack    */
  1273.     struct two_pool *act_sta = NULL ; /* Stored list of acceptable actions    */
  1274.     int    ss = sta_stack->val.state ;    /* The top of the state stack            */
  1275.     struct two_pool *tmp_tp ;            /* utility variables            */
  1276.     struct two_pool *tmp ;
  1277.     short    red,dr ;
  1278.     int    n ,n_temp_sta_stack ;
  1279.  
  1280.     /* Get the tokens that are acceptable to the top state on the stack.  */
  1281.  
  1282.     copystack(sta_stack,&temp_sta_stack,&n_temp_sta_stack);
  1283.  
  1284.     while ((dr = def_action[ss - 1]) != 0) {
  1285.         tmp = TALLOC() ;        /* act_sta with := ss    */
  1286.         tmp->val.state = ss ;
  1287.         tmp->link = act_sta ;
  1288.         act_sta = tmp ;
  1289.  
  1290.         red = dr - NUM_STATES - 1 ;
  1291.  
  1292.         /*    Strip "rhslen[red]" elements from the temp_sta_stack */
  1293.         n = rhslen[red] ;
  1294.         if(!n) {
  1295.             tmp = TALLOC() ;
  1296.             tmp->link = temp_sta_stack ;
  1297.             temp_sta_stack = tmp ;
  1298.         }
  1299.         else if( n > 1 ) {
  1300.             while( --n > 1 )
  1301.                 temp_sta_stack = temp_sta_stack->link ;
  1302.             tmp = temp_sta_stack ;
  1303.             temp_sta_stack = temp_sta_stack->link ;
  1304.         }
  1305.         else if (n < 0)
  1306.             break ;
  1307.         temp_sta_stack->val.state =    
  1308.           action((int)(temp_sta_stack->link->val.state),lhs[red]);
  1309.         ss = temp_sta_stack->val.state ;
  1310.     }
  1311.  
  1312.     tmp = TALLOC() ;
  1313.     tmp->val.state = ss ;
  1314.     tmp->link = act_sta ;
  1315.     act_sta = tmp ;
  1316.  
  1317.  
  1318.     /* 
  1319.      * POSS_TOK := +/{ACTION_TOKENS(s) : s in act_sta};                
  1320.      * Since ACTION_TOKENS(s) is a set of numbers, for each s we must
  1321.      * loop over the set, adding the values to the list POSS_TOK
  1322.      */
  1323.     POSS_TOK = NULL ;
  1324.     while (act_sta != NULL) {
  1325.         int a ;
  1326.  
  1327.         for(a = ACTION_TOKENS_INDEX[(int)(act_sta->val.state) - 1] ;
  1328.           a <= (ACTION_TOKENS_INDEX[(int)(act_sta->val.state)] - 1) ; a ++ )
  1329.         {
  1330.             /* Add ACTION_TOKENS(a) to the list */
  1331.             tmp_tp = TALLOC() ;
  1332.             tmp_tp->link = POSS_TOK ;
  1333.             tmp_tp->val.state = ACTION_TOKENS[a] ;
  1334.             POSS_TOK = tmp_tp ;
  1335.         }
  1336.         act_sta = act_sta->link ;
  1337.     }
  1338. }
  1339.  
  1340. static void get_next(int k)                /*;get_next*/
  1341. {
  1342.     /* This procedure ensures that tokens contains at least k tokens.  
  1343.      * Note that tokind always points to the next token, so that the
  1344.      * array must be read in in reverse order
  1345.      */
  1346.  
  1347.     int i;
  1348.  
  1349.     /* First check if this is the first time, and if so allocate space for
  1350.      * tokens.
  1351.      */
  1352.  
  1353.     if (tokind == -1) {
  1354.         tokens =
  1355.           (struct prsstack **)malloc((unsigned)(2*k*sizeof(struct prsstack *)));
  1356.         toksiz = 2 * k;
  1357.     }
  1358.  
  1359.     /* for now only put in k-1 tokens, since the current token has to be
  1360.      * inserted.
  1361.      */
  1362.     for (i = k - ((toksiz + (tokind - tokbottom + 1)) % toksiz); i>0 ; i--) {
  1363.         tokbottom = (toksiz + tokbottom - 1) % toksiz;
  1364.         tokens[tokbottom] = gettok();
  1365.     }
  1366.     if (tokind == -1)
  1367.         tokind = toksiz - 1;
  1368. }
  1369.  
  1370. add_to_top(struct prsstack *tok)                        /* ;add_to_top */
  1371. {
  1372.     /* this procedure replaces the old ADDTOTOP macro, which assumed there
  1373.      * was room in tokens and did not check for a full queue before adding
  1374.      * a new token
  1375.      * We now check at each insertion, and expand the queue as necessary
  1376.      */
  1377.   short siz;
  1378.  
  1379.     siz = (tokind - tokbottom + 1 ) % toksiz;
  1380.     if (siz == toksiz - 1)     /* queue is full */
  1381.     {                        /* reallocate and enlarge ! */
  1382.         toksiz = toksiz + 50;
  1383.         tokens = (struct prsstack **) erealloc(tokens, (unsigned) (toksiz * 
  1384.                         sizeof(struct prsstack *)));
  1385.     }
  1386.     tokens[tokind = (tokind +1) % toksiz] = tok;
  1387. }
  1388.